package com.hk.blog.service.impl;

import com.hk.blog.domain.Role;
import com.hk.blog.repository.jpa.RoleRepository;
import com.hk.blog.service.RolePermissionService;
import com.hk.blog.service.RoleService;
import com.hk.blog.vo.RolePermBean;
import com.hk.commons.JsonResult;
import com.hk.commons.util.BeanUtils;
import com.hk.core.data.jpa.repository.BaseJpaRepository;
import com.hk.core.service.exception.ServiceException;
import com.hk.core.service.jpa.impl.JpaServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;

@Service
@RequiredArgsConstructor
public class RoleServiceImpl extends JpaServiceImpl<Role, Long>
        implements RoleService {

    private final RoleRepository roleRepository;

    private final RolePermissionService rolePermissionService;

    @Override
    protected ExampleMatcher ofExampleMatcher() {
        return super.ofExampleMatcher()
                .withMatcher("roleCode", ExampleMatcher.GenericPropertyMatchers.contains())
                .withMatcher("roleName", ExampleMatcher.GenericPropertyMatchers.contains());
    }

    @Override
    protected BaseJpaRepository<Role, Long> getBaseRepository() {
        return roleRepository;
    }

    @Override
    @Transactional
    public Role insert(Role role, Function<Role, Role> function) {
        role = function.apply(role);
        if (roleRepository.existsByRoleCode(role.getRoleCode())) {
            throw new ServiceException(JsonResult.failure("角色已存在"));
        }

        return internalSaveOrUpdate(role);
    }

    private Role internalSaveOrUpdate(Role role) {
        Role save;
        if (role instanceof RolePermBean rolePermBean) {
            Role newRole = new Role();
            BeanUtils.copyNotNullProperties(role, newRole);
            save = roleRepository.save(newRole);
            rolePermissionService.updateRolePerms(save.getId(), rolePermBean.getPermIds());
        } else {
            save = roleRepository.save(role);
        }
        return save;
    }

    @Override
    @Transactional
    public Role updateById(Role role, Function<Role, Role> function) {
        role = function.apply(role);
        Optional<Role> optionalPermission = roleRepository.findByRoleCode(role.getRoleCode());
        if (optionalPermission.isPresent() && !Objects.equals(optionalPermission.get().getId(), role.getId())) {
            throw new ServiceException(JsonResult.failure("该角色已存在"));
        }
        return internalSaveOrUpdate(role);
    }
}
